package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.utils.InfoUtil;
import com.alibaba.citrus.cr.common.enums.ordercenter.AsyncMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderPushStatusEnum;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.exception.ProcessException;
import com.alibaba.citrus.ots.common.util.JsonUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crb2btradecenter.api.orderwrite.dto.SapDeleteSaleOrderRequest;
import com.epoch.app.crb2btradecenter.api.orderwrite.service.OrderWriteService;
import com.epoch.app.crb2btradecenter.domain.order.dto.QueryByOuterOrderIdsRequest;
import com.epoch.app.crb2btradecenter.domain.order.model.Order;
import com.epoch.app.crb2btradecenter.domain.order.service.OrderService;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.crb2btradecenter.orderbackup.service.OrderBackUpService;
import com.epoch.app.crunifiedinventory.consignmentorder.model.ConsignmentOrder;
import com.epoch.app.crunifiedinventory.consignmentorder.service.ConsignmentOrderService;
import com.epoch.app.crunifiedinventory.consignmentorderline.model.ConsignmentOrderLine;
import com.epoch.app.crunifiedinventory.consignmentorderline.service.ConsignmentOrderLineService;
import com.epoch.app.crunifiedinventory.model.dto.*;
import com.epoch.app.crunifiedinventory.service.CrUnifiedInventoryService;
import com.epoch.app.mnordercenter.model.dto.CommonAsyncMessageResponse;
import com.epoch.app.mnordercenter.model.dto.PushOrderInfoToMnSideRequestOrderInfo;
import com.epoch.app.otsapplicationadaptersdk.model.dto.MnSapIf019Request;
import com.epoch.app.otsapplicationadaptersdk.model.dto.MnSapIf019SDO;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetrySaveRequest;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.model.enums.SapApiCode;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommResponse;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommSDO;
import com.epoch.app.otsapplicationadaptersdk.sapretrywrite.service.SapRetryWriteService;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif019v2.service.MnSapIf019V2Service;
import com.epoch.app.otsunifiedinventory.model.dto.WmsSDO;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author
 * @date 2021/10/12
 * @Description sap请求平台同步销售单删除
 */
@Component
@Primary
public class MnSapIf019V2ServiceImpl implements MnSapIf019V2Service {
    private final Log log = Log.getLogger(MnSapIf019V2ServiceImpl.class);

    @Autowired
    private OrderWriteService orderWriteService;
    @Resource
    private OrderService orderService;
    @Resource
    private ConsignmentOrderService consignmentOrderService;
    @Resource
    private ConsignmentOrderLineService consignmentOrderLineService;
    @Resource
    private SapRetryWriteService sapRetryWriteService;
    @Resource
    private EpochMessageService messageService;
    @Resource
    private CrUnifiedInventoryService crUnifiedInventoryService;
    @Resource
    private OrderBackUpService orderBackUpService;
    private static final List<String> saleOrderExtList = Lists.newArrayList("ZORO","ZORA","ZRE5");

    private static final String SPEC_ORG = "1171";
    //退货销售单类型 不预占库存
    private final static List<String> returnGoodsExtList = Lists.newArrayList("ZRE2","ZRE3");
    public static final String EXCHANGE= "exchange";
    private static final String EXCHANGE_ORDER_TYPE = "ZCH2";

    private static final String SAP019 = "MnSapIf019V2$externalSyncSaleOrderDelete";


    @Override
    @ProcessInvoker(remark = "MnSapIf019V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    public MnSapCommResponse externalSyncSaleOrderDelete(MnSapIf019Request mnSapIf019Request) {
        log.info("MnSapIf019Request mnSapIf019Request:" + JSONObject.toJSONString(mnSapIf019Request));
        MnSapCommResponse response = new MnSapCommResponse();
        response.setInterfacePath(mnSapIf019Request.getMessageHeader().getInterfacePath());
        response.setMessageId(mnSapIf019Request.getMessageHeader().getMessageId());
        List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
        try {
            List<MnSapIf019SDO> mnSapIf019SDOS = mnSapIf019Request.getData();

            List<String> outOrderIds = mnSapIf019SDOS.stream().map(sdo -> sdo.getOutOrderId()).collect(Collectors.toList());
            QueryByOuterOrderIdsRequest pageQueryRequest = new QueryByOuterOrderIdsRequest();
            pageQueryRequest.setOuterOrderIds(outOrderIds);
            pageQueryRequest.setLimit(outOrderIds.size());
            Result<List<Order>> listResult = orderService.queryByOuterOrderIds(pageQueryRequest);
            List<Order> orders = new ArrayList<>();
            if (Objects.nonNull(listResult) && CollectionUtils.isNotEmpty(listResult.getResult())) {
                orders = listResult.getResult();
            }

            for (MnSapIf019SDO data : mnSapIf019SDOS) {
                try {
                    SapDeleteSaleOrderRequest request = new SapDeleteSaleOrderRequest();
                    request.setOutOrderId(data.getOutOrderId());
                    Result<Boolean> deleteSaleOrder = orderWriteService.sapDeleteSaleOrder(request);
                    MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                    if (Objects.isNull(deleteSaleOrder)) {
                        log.error("MnSapIf019V2ServiceImpl_deleteSaleOrderError");
                        mnSapCommSDO.setStatus("E");
                        mnSapCommSDO.setMessage("删除销售订单异常");
                        mnSapCommSDO.setItem(null);
                        mnSapCommSDOS.add(mnSapCommSDO);
                        response.setData(mnSapCommSDOS);
                        log.error("MnSapIf019V2Service.deleteSaleOrder error: " + JSON.toJSONString(response));
                        saveSapRetry(mnSapIf019Request,"删除销售订单异常");
                        return response;
                    }
                    if (!deleteSaleOrder.isSuccess()){
                        log.error("MnSapIf019V2ServiceImpl_deleteSaleOrderError");
                        mnSapCommSDO.setStatus("E");
                        mnSapCommSDO.setMessage(deleteSaleOrder.getMessage());
                        mnSapCommSDO.setItem(null);
                        mnSapCommSDOS.add(mnSapCommSDO);
                        response.setData(mnSapCommSDOS);
                        log.error("MnSapIf019V2Service.deleteSaleOrder error: " + JSON.toJSONString(response));
                        saveSapRetry(mnSapIf019Request, deleteSaleOrder.getMessage());
                        return response;
                    }

                    mnSapCommSDO.setStatus("S");
                    mnSapCommSDO.setMessage("订单：" + data.getOutOrderId() + "删除成功");
                    mnSapCommSDOS.add(mnSapCommSDO);
                } catch (RuntimeException e) {
                    if (e.getMessage() != null && e.getMessage().contains("FacadeException")) {
                        //FacadeException fe=(FacadeException)e;
                        //log.error("MnSapIf019ServiceImpl.externalSyncSaleOrderDelete business exception, error code:{}, error message:{}", fe.getErrorCode(), fe.getErrorMessage());
                        log.error("MnSapIf019ServiceImpl.externalSyncSaleOrderDelete business exception,error message:{}", e.getMessage());
                        MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                        mnSapCommSDO.setStatus("E");
                        //mnSapCommSDO.setMessage(fe.getErrorMessage());
                        mnSapCommSDO.setMessage(e.getMessage().substring(e.getMessage().indexOf("FacadeException: ") + "FacadeException: ".length(), e.getMessage().length()));
                        mnSapCommSDOS.add(mnSapCommSDO);
                        //加入重试队列 重试由定时器执行
                        saveSapRetry(mnSapIf019Request, e.getMessage());
                    } else {
                        throw e;
                    }
                }
            }
            // 异步发送kafka消息
            asyncSendMsgToKafka(orders);
        } catch (Exception e) {
            log.error("MnSapIf019ServiceImpl.externalSyncSaleOrderDelete unknow exception, error:{}", e);
            throw new ProcessException("OTS-05-001-10-16-047");
        }
        response.setData(mnSapCommSDOS);
        return response;
    }

    /**
     * 发送mq消息，异步发送kafka消息通知应用端
     */
    private void asyncSendMsgToKafka(List<Order> orders){
        if (CollectionUtils.isEmpty(orders)) {
            return;
        }

        String fromSys = "";
        String businessUnitCode = "";
        List<PushOrderInfoToMnSideRequestOrderInfo> pushOrderInfos = new ArrayList<>();
        for (Order order : orders) {
            if (!JsonUtil.checkOrderCenterTag(order.getFeatures())) {
                // 非订单中心订单不发kafka消息
                continue;
            }
            if (StringUtils.isBlank(fromSys) && StringUtils.isNotBlank(order.getFromSys())) {
                fromSys = order.getFromSys();
            }
            if (StringUtils.isBlank(businessUnitCode) && StringUtils.isNotBlank(order.getBisUnitOutCode())) {
                businessUnitCode = order.getBisUnitOutCode();
            }

            PushOrderInfoToMnSideRequestOrderInfo pushOrderInfo = new PushOrderInfoToMnSideRequestOrderInfo();
            pushOrderInfo.setSalesOrderNo(order.getOrderBizId());
            pushOrderInfo.setOrderStatus(SalesOrderPushStatusEnum.SUCCESS_DELETE.getOrderStatusCode());
            pushOrderInfos.add(pushOrderInfo);
        }
        if (CollectionUtils.isEmpty(pushOrderInfos)) {
            return;
        }

        CommonAsyncMessageResponse commonAsyncMessageResponse = new CommonAsyncMessageResponse();
        commonAsyncMessageResponse.setEventCode(AsyncMessageEventEnum.SALES_ORDER_DELETE.getValue());
        commonAsyncMessageResponse.setEventName(AsyncMessageEventEnum.SALES_ORDER_DELETE.getLabel());
        commonAsyncMessageResponse.setEventTime(String.valueOf(new Date().getTime()));
        commonAsyncMessageResponse.setFromSys(fromSys);
        commonAsyncMessageResponse.setBusinessUnitCode(businessUnitCode);
        commonAsyncMessageResponse.setData(pushOrderInfos);

        messageService.sendMessage("ORDER_STATUSCHANGE_PUSH_MESSAGE", "CR_SALEORDER_V2", "SaleOrderPushMn",
                JSONObject.toJSONString(commonAsyncMessageResponse));
        log.info("MnSapIf019V2Service#asynSendMsgToKafka commonAsyncMessageResponse: {}", commonAsyncMessageResponse);
    }

    private void handleInventory(Order order, List<OrderLine> orderLines,MnSapIf019SDO datum){
        log.info("MnSapIf019V2ServiceImpl_externalSyncSaleOrderDelete_handleInventory,order:{},orderLines:{}",
                JSON.toJSONString(order),JSON.toJSONString(orderLines));
        if (order ==null || CollectionUtils.isEmpty(orderLines)){
            log.info("MnSapIf019V2ServiceImpl_externalSyncSaleOrderDelete_handleInventory_orderOrOrderLinesIsNull");
            return;
        }
        ConsignmentOrderLoadListRequest consignmentOrderLoadListRequest = new ConsignmentOrderLoadListRequest();
        consignmentOrderLoadListRequest.setSalesOrderId(order.getId().toString());
        consignmentOrderLoadListRequest.setStatus(1);
        if ((StringUtils.isNotBlank(datum.getOrderType())&&saleOrderExtList.contains(datum.getOrderType()))&&(
                StringUtils.isNotBlank(datum.getSaleOrganizationCode())&& SPEC_ORG.equalsIgnoreCase(datum.getSaleOrganizationCode())
        )){
            consignmentOrderLoadListRequest.setSalesOrderId(null);
            consignmentOrderLoadListRequest.setOuterStoOrderId(datum.getOutOrderId());
        }
        log.info("MnSapIf019V2ServiceImpl_externalSyncSaleOrderDelete_handleInventory_loadConsignmentOrderList:{}",JSON.toJSONString(consignmentOrderLoadListRequest));
        Result<List<ConsignmentOrder>> listResult = consignmentOrderService.loadConsignmentOrderList(consignmentOrderLoadListRequest);
        if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())) {
            for (ConsignmentOrder consignmentOrder : listResult.getResult()) {
                ConsignmentOrderLineLoadListRequest consignmentOrderLineLoadListRequest = new ConsignmentOrderLineLoadListRequest();
                consignmentOrderLineLoadListRequest.setConsignmentOrderId(consignmentOrder.getId().toString());
                Result<List<ConsignmentOrderLine>> loadConsignmentOrderLineList = consignmentOrderLineService.loadConsignmentOrderLineList(consignmentOrderLineLoadListRequest);
                if (loadConsignmentOrderLineList == null || CollectionUtils.isEmpty(loadConsignmentOrderLineList.getResult())){
                    continue;
                }
                List<ConsignmentOrderLine> consignmentOrderLines = loadConsignmentOrderLineList.getResult();
                if (EXCHANGE_ORDER_TYPE.equalsIgnoreCase(order.getOrderType())){
                    // 如果不是换货的标记就过滤
                    boolean match = consignmentOrderLines.stream().anyMatch(x -> StringUtils.isNotBlank(x.getOuterSoLineId()) && Integer.valueOf(x.getOuterSoLineId().trim()) % 2 == 0);
                    if (!match){
                        continue;
                    }
                }
                String outDeliveryOrderNo = consignmentOrder.getOuterDeliveryOrderId();
                String wareHouseCode = order.getWareHouseCode();
                OccupyReleaseRequest occupyReleaseRequest = new OccupyReleaseRequest();
                //获取 outSOLineId - quantity 理论上行不会重复
                Map<String, List<ConsignmentOrderLine>> lineMap = loadConsignmentOrderLineList.getResult().stream().collect(Collectors.groupingBy(ConsignmentOrderLine::getOuterSoLineId));
                List<InvOperateLine> invOperateLineList = Lists.newArrayList();
                lineMap.forEach((k,v)->{
                    InvOperateLine invOperateLine = new InvOperateLine();
                    if (CollectionUtils.isEmpty(v)){
                        //error
                        log.error("MnSapIf019V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-163");
                    }
                    String scItemId = v.get(0).getScItemId();
                    if (StringUtils.isBlank(scItemId)){
                        //error
                        log.error("MnSapIf019V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-164");
                    }
                    invOperateLine.setGoodsId(scItemId);
                    invOperateLine.setDeleted(true);
                    invOperateLine.setType("2");
                    invOperateLine.setOutOrderId(outDeliveryOrderNo);
                    //发现没有时间戳 用交货单号代替了.
                    invOperateLine.setOutSubOrderId(outDeliveryOrderNo);
                    invOperateLine.setWarehouseAreaId(wareHouseCode);
                    //
                    WmsSDO wmsSDO = InfoUtil.getWmsSDO(wareHouseCode);
                    if (StringUtils.isBlank(wmsSDO.getWarehouseId())){
                        //error
                        log.error("MnSapIf019V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-165");
                    }
                    invOperateLine.setWarehouseId(wmsSDO.getWarehouseId());
                    invOperateLine.setReferenceOrderId(order.getId().toString());
                    List<OrderLine> orderLineResult = orderLines.stream().filter(x -> Objects.equals(x.getOuterOrderLineId(), k)).collect(Collectors.toList());
                    if (CollectionUtils.isEmpty(orderLineResult)){
                        //error
                        log.error("MnSapIf019V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-166");
                    }
                    OrderLine orderLine = orderLineResult.get(0);
                    invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                    Long quantity = v.stream().mapToLong(x -> {
                        if (StringUtils.isBlank(x.getQty())) {
                            return 0L;
                        }
                        BigDecimal bigDecimal = new BigDecimal(x.getQty().trim());
                        return bigDecimal.movePointRight(3).longValue();
                    }).sum();
                    if (quantity <= 0 ){
                        //error
                        log.error("MnSapIf019V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-167");
                    }
                    invOperateLine.setQuantity(quantity.toString());
                    invOperateLineList.add(invOperateLine);
                });
                if (CollectionUtils.isEmpty(invOperateLineList)){
                    //error
                    log.error("MnSapIf019V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                    throw new FacadeException("OTS-03-005-00-15-168");
                }
                occupyReleaseRequest.setInvOperateLineList(invOperateLineList);
                log.info("MnSapIf018V2ServiceImpl_occupyRelease,request:{},occupyReleaseRequest:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(occupyReleaseRequest));
                Result<OccupyReleaseResponse> occupyReleaseResponseResult = crUnifiedInventoryService.occupyRelease(occupyReleaseRequest);
                log.info("MnSapIf018V2ServiceImpl_occupyRelease,result:{},occupyReleaseRequest:{},occupyReleaseResult:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(occupyReleaseRequest),JSON.toJSONString(occupyReleaseResponseResult));
                if (occupyReleaseResponseResult == null || !occupyReleaseResponseResult.isSuccess()){
                    //error
                    throw new FacadeException("OTS-03-005-00-15-169");
                }
            }

        }

    }



    //释放预占
    private static boolean isSaleOrder(MnSapIf019SDO datum){
        //013接口会同步特殊的销售单，判断ext=ZORO且销售组织是1171的交货单，修改为销售订单类型的交货单
        if ((StringUtils.isNotBlank(datum.getOrderType())&&saleOrderExtList.contains(datum.getOrderType()))&&(
                StringUtils.isNotBlank(datum.getSaleOrganizationCode())&& SPEC_ORG.equalsIgnoreCase(datum.getSaleOrganizationCode())
        )){
            return true;
        }
        //退货不预占库存
        if (returnGoodsExtList.contains(datum.getOutOrderId())){
            return false;
        }
//        //如果是换货的只接收换货的交货单号
//        if (EXCHANGE_ORDER_TYPE.equals(datum.getOrderType())){
//            if (CollectionUtils.isNotEmpty(datum.getItems())){
//                boolean isExchange = datum.getItems().stream().anyMatch(x -> StringUtils.isNotBlank(x.getOuterSoLineId()) && Integer.valueOf(x.getOuterSoLineId().trim()) % 2 == 0);
//                if (isExchange){
//                    return true;
//                }
//            }
//        }
        if (StringUtils.isNotBlank(datum.getOutOrderId())){
            return true;
        }

        return false;
    }

    /**
     * 2022.11.07 019删除销售订单失败重试
     * **/
    private void saveSapRetry(MnSapIf019Request request,String message){
        try {
            if (request == null){
                return;
            }
            if (CollectionUtils.isEmpty(request.getData()) || request.getData().get(0) == null){
                return;
            }
            MnSapIf019SDO sdo = request.getData().get(0);
            SapRetrySaveRequest sapRetrySaveRequest = new SapRetrySaveRequest();
            String requestJson = JSON.toJSONString(request);
            sapRetrySaveRequest.setParam(requestJson);
            sapRetrySaveRequest.setMsg(message);
            sapRetrySaveRequest.setMessageId(request.getMessageHeader().getMessageId());
            sapRetrySaveRequest.setApiCode(SapApiCode.SAP019.getValue());
            sapRetrySaveRequest.setOutKey(sdo.getOutOrderId());
            sapRetrySaveRequest.setStatus(RetryStatus.FAIL.getValue());
            sapRetryWriteService.save(sapRetrySaveRequest);
        }catch (Throwable e){
            log.error("MnSapIf019V2ServiceImpl_saveSapRetryError",e);
        }
    }


}
